package Or

import (
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
	"sync/atomic"
)

type TableIndex struct{}

func hitSpecify(s global.StartPart) (hitIndexName string) {
	//指定partition name会导致无法使用索引，进行全表扫描，且该sql为查询数据，已经通过索引列范围确定查询范围，所以不需要指定分区
	if len(s.SelectColumn.IndexName) > 0 && !strings.EqualFold(s.TableInfo.PartitionName, "single") && len(s.TableInfo.PartitionName) > 0 {
		hitIndexName = fmt.Sprintf(" /*+ index(T %v) */ ", s.SelectColumn.IndexName)
	}
	return
}
func (or TableIndex) resultCol(asSelectColumn []string) (r string) {
	var l []string
	for _, v := range asSelectColumn {
		l = append(l, fmt.Sprintf("t.\"%v\" ", v))
	}
	return strings.Join(l, ",")
}
func (or TableIndex) selectCol(selectC []string) (r string) {
	var selectIndexColumn []string
	for _, v := range selectC {
		selectIndexColumn = append(selectIndexColumn, fmt.Sprintf("\"%v\"", v))
	}
	return strings.Join(selectIndexColumn, ",")
}
func (or TableIndex) orderByNull(s global.StartPart) (r string) {
	if atomic.LoadInt32(s.WhereGenerate.NullBool) == 1 {
		return fmt.Sprintf(" order by \"%v\" ASC NULLS FIRST", strings.Join(s.WhereGenerate.IndexColumn, "\" ASC NULLS FIRST,\""))
	}
	return fmt.Sprintf(" order by \"%v\"", strings.Join(s.WhereGenerate.IndexColumn, "\",\""))
}
func (or TableIndex) whereSplicing(whereCondition []string) (r string) {
	if len(whereCondition) > 0 {
		return fmt.Sprintf(" where %v", strings.Join(whereCondition, " and "))
	}
	return ""
}

type colAndWhereResult struct {
	selectColumn, asSelectColumn, whereCondition []string
	orderByColumn                                string
}

// StartPart oracle库下查询表的索引列数据的始末位置，并进行去重排序
func (or TableIndex) StartPart(s global.StartPart) (result any, err error) {
	var (
		event = "[oracleStartPart]"
		rep   = global.StartPartReturnResult{}
		res   colAndWhereResult
		f1    any
	)
	LimitSeq1 := atomic.LoadInt64(s.Limit.Pagination) + 1
	if res, err = colAndWhere(s); err != nil {
		return
	}
	rep.BaseResult.Sql = fmt.Sprintf("select * from ( \n"+
		"select %v,rownum rn from ( \n"+
		"select %v %s from ( \n"+
		"select %v from %v %v T where 1 = 1 %v) T %s %s) t \n"+
		"where rownum<=%d) \n"+
		"where rn>%d",
		or.resultCol(res.asSelectColumn), hitSpecify(s), strings.Join(res.selectColumn, ","),
		or.selectCol(s.SelectColumn.IndexColumn), tableObject(s.TableInfo.Schema, s.TableInfo.BackendTableName, s.TableInfo.PartitionName),
		specifyScn(s.Input.Scn), rowsLimitC(s.TableInfo.RowsLimit),
		or.whereSplicing(res.whereCondition), or.orderByNull(s),
		LimitSeq1,
		atomic.LoadInt64(s.Limit.Pagination))
	if rep.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
		Ss:           s,
		Event:        event,
		SelectSqlStr: rep.BaseResult.Sql,
		Expect:       ETL.Map,
		ShardName:    "single",
	}); err != nil {
		return
	}
	rep.Result = f1.(map[string]any)
	return rep, nil
}
